#!/bin/bash
# 备份 Docker 容器内 PostgreSQL 数据库并清理旧文件
# 使用方法: crontab 30 3 * * * source $HOME/.bash_profile && sh /sumz/script/pg_bak.sh >> /sumz/pg_bak.log 2>&1

# 启用 pipefail，确保管道中任一命令失败时退出状态非 0
set -o pipefail

# 配置
BACKUP_DIR="/data/bak"  # 备份根目录
PROJECTS=("h")                        # 需要备份的数据库
PG_USER="sumz"                           # PostgreSQL 用户名
PG_PASS="Sumz"                          # PostgreSQL 密码（建议改为环境变量）
DOCKER_CMD="/usr/bin/docker"            # docker 命令路径
CONTAINER_NAME="sumz-polardb-postgresql.base-1"   # Docker 容器名称
KEEP_DAYS=3                             # 保留天数
KEEP_FRIDAY=false                       # 是否保留星期五的备份
BAK_EXEC=/home/postgres/tmp_basedir_polardb_pg_1100_bld/bin/pg_dump

# 检查依赖
for cmd in "$DOCKER_CMD" zip; do
    if ! command -v "$cmd" &> /dev/null; then
        echo "错误: 未找到命令 $cmd，请检查环境"
        exit 1
    fi
done

# 备份函数
backup_database() {
    local db_name="$1"
    local backup_path="$BACKUP_DIR/$db_name"
    local timestamp=$(date +%Y%m%d-%H%M%S)
    local backup_file="$backup_path/${db_name}-${timestamp}.sql.zip"

    mkdir -p "$backup_path" || {
        echo "错误: 创建目录 $backup_path 失败"
        return 1
    }

    echo "开始备份 $db_name 到 $backup_file"
    # 使用管道直接压缩，避免临时文件
    $DOCKER_CMD exec "$CONTAINER_NAME" \
        env PGPASSWORD="$PG_PASS" "$BAK_EXEC" -U "$PG_USER" -h 127.0.0.1 -d "$db_name" 2>/tmp/pg_bak_err | zip -r "$backup_file" -

    local exit_code=$?
    if [ $exit_code -eq 0 ]; then
        echo "备份 $db_name 成功"
    else
        echo "错误: 备份 $db_name 失败，退出码: $exit_code"
        if [ -s /tmp/pg_bak_err ]; then
            echo "错误详情: $(cat /tmp/pg_bak_err)"
        fi
        rm -f /tmp/pg_bak_err
        return 1
    fi
}

# 删除旧备份函数
clean_old_backups() {
    local db_name="$1"
    local backup_path="$BACKUP_DIR/$db_name"

    if [ ! -d "$backup_path" ]; then
        echo "警告: 目录 $backup_path 不存在，跳过清理"
        return 0
    fi

    echo "清理 $db_name 的旧备份（保留 $KEEP_DAYS 天，星期五备份除外）"
    find "$backup_path" -type f -name "*.sql.zip" -mtime +"$KEEP_DAYS" | while read -r file; do
        file_day=$(date -r "$file" +%w)
        if [ "$KEEP_FRIDAY" = true ] && [ "$file_day" -eq 5 ]; then
            echo "保留星期五备份: $file"
        else
            rm -f "$file" && echo "删除旧备份: $file"
        fi
    done
}

# 主逻辑
for db in "${PROJECTS[@]}"; do
    backup_database "$db"
    clean_old_backups "$db"
done

echo "备份和清理完成: $(date +%Y-%m-%d_%H:%M:%S)"